#include "shift_register.h"

CShiftRegister::CShiftRegister() :
	mReady(false),
	mRegisterLength(0),
	mSequenceLength(0)
{

}

CShiftRegister::~CShiftRegister()
{
	mReady = false;
}

bool CShiftRegister::setParameters(unsigned int pRegisterLength,
		unsigned int pSequenceLength, std::vector<unsigned int>& pFeedback)
{
	mReady = false;
	mFeedback.clear();

	// set new parameters

	mRegisterLength = pRegisterLength;
	mSequenceLength = pSequenceLength;

	for (unsigned int i = 0; i < pFeedback.size(); i++) {
		// check feedback positions, have to be within register range
		if (pFeedback.at(i) > mRegisterLength) {
			return false;
		}

		// ... if everything's fine, add element to mFeedback
		mFeedback.push_back(pFeedback.at(i));
	}

	mReady = true;
	return true;
}

bool CShiftRegister::getRandomSequence(bool*& pSequence)
{
	if (!mReady) {
		return false;
	}

	mRegister.clear();

	// initialize register with sequence of 1, 0, ... values

	for (unsigned int i = 1; i <= mRegisterLength; i++) {
		mRegister.push_back(((i % 2) == 0) ? false : true);
	}

	// compute new register values until we have enough output (mSequenceLength)

	unsigned int lCnt(0); // index for pSequence

	// the loop runs mRegisterLength more times than needed for the output
	// because the first mRegisterLength values from the output are equal to the
	// initialization and hence aren't used
	for (unsigned int i = 0; i < mSequenceLength + mRegisterLength; i++) {
		// xor every feedback position

		bool lInput(mRegister.at(mFeedback.at(0) - 1)); // 1. feedback position
		for (unsigned int j = 1; j < mFeedback.size(); j++) {
			lInput ^= mRegister.at(mFeedback.at(j) - 1); // other feedback positions
		}

		// set output bit (last element of register)
		// note: the first mRegisterLength elements are ignored for the output

		if (i >= mRegisterLength) {
			pSequence[lCnt++] = mRegister.back();
		}

		// shift the register by 1

		mRegister.pop_back();

		// add feedback element at the front

		mRegister.insert(mRegister.begin(), lInput);
	}

	return true;
}

